package edu.washington.ling.syntric.util;

import java.io.PrintStream;

import edu.washington.ling.syntric.io.Example;
import edu.washington.ling.syntric.io.TreeReader;
import edu.washington.ling.syntric.io.TreeRepresentation;
import edu.washington.ling.syntric.io.TreeWriter;
import edu.washington.ling.syntric.struct.error.InvalidValueException;
import edu.washington.ling.syntric.struct.error.UnreadableRepresentationException;

public class LaTeXUtils {
	
	public static String formatPreamble(String title) {
		String preamble = "\\documentclass[12pt, landscape]{article}\n";
		preamble += String.format("\\title{%s}\n", title);
		preamble += "\\date{\\today}\n";
		preamble += "\\usepackage[a0paper, vmargin=2cm, hmargin=2cm]{geometry}\n";
		preamble += "\\usepackage{lingmacros}\n";
		preamble += "\\usepackage{tikz}\n";
		preamble += "\\usepackage{tikz-qtree}\n";
		preamble += "\\usetikzlibrary{arrows,positioning,shapes}\n";
		preamble += "\\tikzset{\n";
		preamble += "\t%Define standard arrow tip\n";
		preamble += "\t>=stealth',\n";
		preamble += "\t%Define DS link style\n";
		preamble += "\tlink/.style={\n";
		preamble += "\t\t<-,\n";
		preamble += "\t\tthick,\n";
		preamble += "\t\tdotted,},\n";
		preamble += "\t%Define DS token style\n";
		preamble += "\ttoken/.style={\n";
		preamble += "\t\trectangle split,\n";
		preamble += "\t\trectangle split parts=2,}\n";
		preamble += "}\n";
		preamble += "\\usepackage{gb4e}\n";
		preamble += "\\begin{document}\n";
		preamble += "\\tikzstyle{every picture}+=[remember picture]\n";
		preamble += "\\maketitle\n";
		return preamble;
	}
	public static String formatForLabel(String s) {
		s = s.replaceAll("\\_", "\\\\_");
		s = s.replaceAll("\\$", "\\\\\\$");
		s = s.replaceAll("\\%", "\\\\%");
		s = s.replaceAll("\\&", "\\\\&");
		return s;
	}
	public static String formatForID(String s) {
		s = s.replaceAll("\\)", "rpar");
		s = s.replaceAll("\\(", "lpar");
		s = s.replaceAll(",", "comma");
		s = s.replaceAll("\\.", "period");
		return s;
	}
	public static String formatIGT(Example exr) {
		String[] origWords = exr.getOriginal().split("\\s");
		String[] glossWords = exr.getGloss().split("\\s");
		int numWords = origWords.length;
		String orig = Utils.join(origWords, "&");
		String gloss = Utils.join(glossWords, "&");
		String igt;
		if (exr.hasTranslation()) {
			igt = String.format("\\shortex{%d}{%s}{%s}{%s}",numWords,orig,gloss,exr.getTranslation());
		}
		else {
			igt = String.format("\\shortexnt{%d}{%s}{%s}",numWords,orig,gloss);
		}
		return igt;
	}
	public static void writeTreeRep(TreeRepresentation tr, PrintStream pStream) {
		pStream.println(String.format("\\begin{item}[]", tr.getLayer()));
		pStream.println(String.format("\\tikz[baseline]\\node[anchor=base,draw=black]{\\bf %s}; ", tr.getLayer()));
		for (String metaData: tr.getMetaData()) {
			pStream.println(String.format("\\tikz[baseline]\\node[anchor=base,draw=red]{\\texttt{%s}}; ", metaData));
		}
		pStream.println(String.format("\\end{item}", tr.getLayer()));
		pStream.println(String.format("\\begin{item}[]", tr.getLayer()));
		for(String line: tr.getTreeLines()) {
			pStream.println(line);
		}
		pStream.println("\\end{item}");
	}
	public static void writeSystemTreeRep(TreeRepresentation tr, int count, PrintStream pStream) {
		pStream.println(String.format("\\begin{item}[]", tr.getLayer()));
		pStream.println(String.format("\\tikz[baseline]\\node[anchor=base,draw=black]{\\bf %s-%d}; ", tr.getLayer(), count));
		for (String metaData: tr.getMetaData()) {
			pStream.println(String.format("\\tikz[baseline]\\node[anchor=base,draw=red]{\\texttt{%s}}; ", metaData));
		}
		pStream.println(String.format("\\end{item}", tr.getLayer()));
		pStream.println(String.format("\\begin{item}[]", tr.getLayer()));
		for(String line: tr.getTreeLines()) {
			pStream.println(line);
		}
		pStream.println("\\end{item}");
	}
	public static void writeExampleRep(Example exr, PrintStream pStream) {
		String[] includeLayers = new String[]{"PS", "DS-Const", "DS+PB", "DS", "PB"};
		writeExampleRep(exr, includeLayers, pStream);
	}
	public static void writeExampleRep(Example exr, String[] includeLayers, PrintStream pStream) {
		String formattedID = LaTeXUtils.formatForLabel(exr.getID());
		pStream.println("\\begin{item}");
	    pStream.println(String.format("{\\bf Example:} %s", formattedID));
		pStream.println("\\begin{itemize}");
		pStream.println("\\begin{item}[]");
		if (exr.hasOriginal() && exr.hasGloss()) {
			pStream.println(LaTeXUtils.formatIGT(exr));
		}
		else {
			pStream.println("IGT is not available for this example.");
		}
		pStream.println("\\end{item}");
		for (String includeLayer: includeLayers) {
			if (exr.hasTreeRep(includeLayer)) {
				TreeRepresentation tr = convertToLaTeX(exr.getTreeRep(includeLayer), exr.getID());
				writeTreeRep(tr, pStream);
			}
		}
		if (exr.hasSystemTreeReps()) {
			pStream.println("\\begin{item}[]");
			pStream.println("System Trees");
			int count = 0;
			for (TreeRepresentation tr: exr.getSystemTreeReps()) {
				writeSystemTreeRep(tr, count, pStream);
				count++;
			}
		}
		pStream.println("\\end{itemize}");
		pStream.println("\\end{item}");
	}
	public static TreeRepresentation convertToLaTeX(TreeRepresentation tr, String id) {
		TreeRepresentation trLatex;
		if (tr.getFormat().equals("latex") == false) {
			trLatex = new TreeRepresentation(tr.getLayer());
			try {
				TreeReader trr = TreeReader.newReader(tr.getFormat());
				TreeWriter trw = TreeWriter.newWriter("latex");
				trLatex = trw.writeTree(trr.readTree(tr));
				trLatex.setMetaData(tr.getMetaData());
			} catch(UnreadableRepresentationException e) {
				trLatex.addMetaData("unreadable");
				System.err.println(String.format("Warning: Could not convert the '%s' to LaTeX for example '%s'", tr.getLayer(), id));
				System.err.println("Representation was unreadable\n");
			} catch(InvalidValueException e) {
				trLatex.addMetaData("unknownFormat");
				System.err.println(String.format("Warning: Could not convert the '%s' to LaTeX for example '%s'", tr.getLayer(), id));
				System.err.println(String.format("Representation was in the unknown format '%s'\n", tr.getFormat()));
			}
		}
		else {
			trLatex = tr;
		}
		return trLatex;
	}
}
